package com.iecas.runnner;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.log.StaticLog;
import com.iecas.context.GlobalContext;
import com.iecas.context.ServerContext;
import com.iecas.entity.Bullet;
import com.iecas.entity.Explosion;
import com.iecas.entity.Tank;
import com.iecas.entity.Wall;
import com.iecas.enums.BizEnum;
import com.iecas.launch.GameFrame;
import com.iecas.request.DeadReq;
import com.iecas.request.DistributeReq;
import com.iecas.request.LoginReq;
import com.iecas.utils.OnlineManager;
import com.iecas.utils.RequestUtils;
import com.iecas.utils.SocketChannelManager;
import lombok.Data;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Data
public class DistributeRunner extends Thread {


    @Override
    public void run() {
        while (true) {
            update();
            if (Thread.currentThread().isInterrupted()) {
                break;
            }
            List<SocketChannel> socketChannels = SocketChannelManager.getSocketChannelList();
            if (CollUtil.isNotEmpty(socketChannels)) {
                // 分发数据
                DistributeReq distributeReq = new DistributeReq();
                distributeReq.setCode(BizEnum.DISTRIBUTE_REQ.getCode());
                distributeReq.setServerContext(GlobalContext.getServerContext());
                ByteBuffer encode = RequestUtils.encode(distributeReq);
                for (SocketChannel socketChannel : socketChannels) {
                    try {
                        encode.flip();
                        socketChannel.write(encode);
                    } catch (IOException e) {
                        StaticLog.error("异常:{}",e.getMessage());
                        String token = SocketChannelManager.remove(socketChannel);
                        ServerContext serverContext = GlobalContext.getServerContext();
                        serverContext.removeTank(token);
                    }
                }
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                interrupt();
            }
        }
    }

    private void update() {
        ServerContext serverContext = GlobalContext.getServerContext();

        List<Bullet> bullets = serverContext.getBulletList();
        updateBullets(bullets);

        List<Explosion> explosions = serverContext.getExplosions();
        updateExplosions(explosions);

    }

    private void updateExplosions(List<Explosion> explosions) {
        List<Explosion> explosionsToRemove = new ArrayList<>();
        for (Explosion explosion : explosions) {
            explosion.update();
            if (explosion.isFinished()) {
                explosionsToRemove.add(explosion);
            }
        }

        explosions.removeAll(explosionsToRemove);
    }

    private void updateBullets(List<Bullet> bullets) {
        List<Bullet> bulletsToRemove = new ArrayList<>();
        for (Bullet bullet : bullets) {
            bullet.move();

            // 检查子弹是否超出边界
            if (bullet.getX() < 0 || bullet.getX() > GameFrame.WIDTH ||
                    bullet.getY() < 0 || bullet.getY() > GameFrame.HEIGHT) {
                bulletsToRemove.add(bullet);
                continue;
            }

            // 检查子弹是否击中墙壁
            ServerContext serverContext = GlobalContext.getServerContext();
            List<Wall> walls = serverContext.getWalls();
            boolean hitWall = false;
            for (Wall wall : walls) {
                if (bullet.intersects(wall)) {
                    bulletsToRemove.add(bullet);
                    hitWall = true;
                    break;
                }
            }

            if (hitWall) continue;

            // 检查玩家子弹是否击中敌人
//            if (bullet.isPlayerBullet()) {
//                for (EnemyTank enemy : enemies) {
//                    if (enemy.isAlive() && bullet.intersects(enemy)) {
//                        bulletsToRemove.add(bullet);
//                        enemy.setAlive(false);
//                        explosions.add(new Explosion(enemy.getX(), enemy.getY()));
//                        score += 100;
//                        break;
//                    }
//                }
//            }
//            // 检查敌人子弹是否击中玩家
//            else {
//                if (player.isAlive() && bullet.intersects(player)) {
//                    bulletsToRemove.add(bullet);
//                    player.setAlive(false);
//                    explosions.add(new Explosion(player.getX(), player.getY()));
//                    break;
//                }
//            }
            Collection<Tank> tanks = serverContext.getTankMap().values();
            List<Explosion> explosions = serverContext.getExplosions();

            for (Tank tank : tanks) {
                if (bullet.intersects(tank)) {
                    bulletsToRemove.add(bullet);
                    SocketChannel socketChannel = SocketChannelManager.get(tank.getToken());
                    DeadReq req = new DeadReq();
                    req.setCode(BizEnum.DEAD_REQ.getCode());
                    ByteBuffer encode = RequestUtils.encode(req);
                    encode.flip();
                    try {
                        socketChannel.write(encode);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    serverContext.removeTank(tank.getToken());
                    OnlineManager.remove(tank.getToken());
                    explosions.add(new Explosion(tank.getX(), tank.getY()));
                    break;
                }
            }
        }

        // 移除需要删除的子弹
        bullets.removeAll(bulletsToRemove);

        // 移除死亡的敌人
//        enemies.removeIf(enemy -> !enemy.isAlive());
    }

    public void shutdown() {
        interrupt();
    }

//    public static void main(String[] args) {
//        DistributeRunner distributeRunner = new DistributeRunner();
//        distributeRunner.start();
//
//        ThreadUtil.sleep(5,TimeUnit.SECONDS);
//
//        distributeRunner.shutdown();
//    }
}
